﻿using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using DotNetRepository.Tools;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace DotNetRepository.UnitTests
{
    [TestClass]
    public class LinqToObjectsTest
    {
        [TestMethod]
        public void TestRepository()
        {
            var repository = Configuration.GetRepository<Customer>();
            var customer = new Customer {ID = Guid.NewGuid(), Name = "Billy Hurd"};
            var order = new Order {ID = Guid.NewGuid(), Description = "Test Order"};
            customer.Orders.Add(order);
            repository.Save(customer);

            var orderRepository = Configuration.GetRepository<Order>();
            var testOrder = orderRepository.GetByID(order.ID);
            Assert.AreEqual(testOrder,order);

            customer = null;
            var results = repository.Where(c => c.Name == "Billy Hurd");
            Assert.AreEqual(results.Count, 1);
            customer = results[0];
            
            Assert.AreEqual(customer.Orders.Count,1);
            Assert.AreEqual(customer.Orders.FirstOrDefault(),testOrder);
            Assert.AreEqual(testOrder.Customer, customer);

            orderRepository.Delete(order);
            testOrder = orderRepository.FirstOrDefault(o => o.Description == "Test Order");
            Assert.IsNull(testOrder);
        }

        [TestMethod]
        public void ValueLockIsThreadSafe()
        {
            var stopwatch = new Stopwatch();
            stopwatch.Start();
            var valueLock = new ValueLock<int>(); 
            var concurrentThreads = 0;
            for (var i = 0; i < 1000; i++)
            {
                var t = new Thread(thr =>
                                       {
                                           using (valueLock.Lock(999))
                                           {
                                               Assert.IsTrue(concurrentThreads == 0);
                                               concurrentThreads++;
                                               Thread.Sleep(10);
                                               Assert.IsTrue(concurrentThreads == 1);
                                               concurrentThreads--;
                                           }
                                       });
                t.Start();
            }
            stopwatch.Stop();
            Console.WriteLine("Time Elapsed: {0} ms", stopwatch.ElapsedMilliseconds);
        }

        [TestMethod]
        public void ValueLock2IsThreadSafe()
        {
            var stopwatch = new Stopwatch();
            stopwatch.Start();
            var valueLock = new ValueLock2<int>();
            var concurrentThreads = 0;
            for (var i = 0; i < 1000; i++)
            {
                var t = new Thread(thr =>
                {
                    using (valueLock.Lock(999))
                    {
                        Assert.IsTrue(concurrentThreads == 0);
                        concurrentThreads++;
                        Thread.Sleep(10);
                        Assert.IsTrue(concurrentThreads == 1);
                        concurrentThreads--;
                    }
                });
                t.Start();
            }
            stopwatch.Stop();
            Console.WriteLine("Time Elapsed: {0} ms", stopwatch.ElapsedMilliseconds);
        }
    }
}
